package com.apobates.jforum.grief.aurl.selector;

import com.apobates.jforum.grief.aurl.core.AUrlMeta;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 文件类型查询器
 */
public class FileTypeSelector extends AUrlMetaGeneralSelector {
    private Optional<String> extName;

    public FileTypeSelector(AUrlMeta rawMeta) {
        super(rawMeta);
        this.extName = getFileExtName(rawMeta);
    }

    @Override
    public Collection<String> getResult() {
        return getExtName().isPresent()?List.of(getExtName().get()): EMPTY.get();
    }

    /**
     * 返回文件的扩展名
     * @return
     */
    private Optional<String> getExtName(){
        return this.extName;
    }

    /**
     * 使用自定义的文件类型校验
     * @param customValider 定义的文件类型校验器
     * @return true 通过/符合指定文件类型
     */
    public boolean isValide(Predicate<String> customValider){
        if(!getExtName().isPresent()){
            return false;
        }
        return customValider.test(getExtName().get());
    }

    /**
     * 是否是图片文件
     * @return true是
     */
    public boolean isImage(){
        return isValide(FileTypeEnum.Image::isLegal);
    }

    /**
     * 是否是Word文件
     * @return true是
     */
    public boolean isWord(){
        return isValide(FileTypeEnum.Word::isLegal);
    }

    /**
     * 是否是Excel文件
     * @return true是
     */
    public boolean isExcel(){
        return isValide(FileTypeEnum.Excel::isLegal);
    }

    /**
     * 是否是PDF文件
     * @return true是
     */
    public boolean isPdf(){
        return isValide(FileTypeEnum.PDF::isLegal);
    }

    /**
     * 是否是音频文件
     * @return true是
     */
    public boolean isAudio(){
        return isValide(FileTypeEnum.Audio::isLegal);
    }

    /**
     * 是否是视频文件
     * @return true是
     */
    public boolean isVedio(){
        return isValide(FileTypeEnum.Vedio::isLegal);
    }

    /**
     * 是否是压缩文件
     * @return true是
     */
    public boolean isZip(){
        return isValide(FileTypeEnum.ZIP::isLegal);
    }

    /**
     * 是否是字体文件
     * @return true是
     */
    public boolean isFont() {
        return isValide(FileTypeEnum.FONT::isLegal);
    }
    /**
     * 当前的扩展名是否在定义的范围之内
     * @return true是, false未在定义的范围之内
     */
    public boolean isDefine(){
        if(getExtName().isPresent()) {
            return FileTypeEnum.getAllExtNames().contains(getExtName().get());
        }
        return false;
    }

    private static Optional<String> getFileExtName(AUrlMeta meta){
        String path = meta.getPath();
        try {
            String tmp = path.substring(path.lastIndexOf(".") + 1);
            return Optional.ofNullable(tmp);
        }catch (Exception e){
            return Optional.empty();
        }
    }
    // docs.fileformat.com/zh/audio/
    private enum FileTypeEnum{
        // docs.fileformat.com/zh/image/
        Image("png", "jpg", "gif", "webp", "jpeg"),
        Word("doc", "docx"),
        Excel("xls","xlsx"),
        PDF("pdf"),
        // docs.fileformat.com/zh/audio/
        // www.whathifi.com/advice/mp3-aac-wav-flac-all-the-audio-file-formats-explained
        Audio("flac", "wav", "aac", "mp3", "alac", "dsd", "aiff", "mqa", "ogg", "midi", "mid", "ape", "amr","ac3"),
        // docs.fileformat.com/zh/video/
        // inevent.com/blog/others/video-formats.html
        Vedio("mp4", "webm", "mpeg", "avi", "wmv", "mov", "flv", "swf", "qt", "mpg", "mpv", "mpe", "mp2", "ogg", "m3u8"),
        // docs.fileformat.com/zh/compression/
        ZIP("zip", "rar", "7z", "tar", "gz", "jar", "ace", "cab", "iso"),
        // docs.fileformat.com/zh/font/
        FONT("woff", "ttf", "otf", "woff2", "fnt", "dfont", "gdr", "sfp", "sfd","tte", "afm", "pfa", "pfb", "pps");
        private String[] extNames;

        private FileTypeEnum(String... extNames){
            this.extNames = extNames;
        }
        public String[] getExtNames(){
            return this.extNames;
        }
        private boolean isLegal(String extName){
            return List.of(extNames).contains(extName.toLowerCase());
        }
        private static List<String> getAllExtNames(){
            List<String> data = Stream.of(values())
                    .map(FileTypeEnum::getExtNames)
                    .flatMap(Stream::of)
                    .collect(Collectors.toList());
            return data;
        }
    }
}
